package com.hsj.common.system.service.impl;

import com.cjxch.supermybatis.base.bean.Pager;
import com.cjxch.supermybatis.core.Service.impl.BaseServiceImpl;
import com.cjxch.supermybatis.core.tools.query.SmCriteria;
import com.hsj.common.system.dao.ISysMenuDao;
import com.hsj.common.system.entity.MenuPrivilegeDo;
import com.hsj.common.system.entity.SysMenuDo;
import com.hsj.common.system.entity.SysRoleMenuDo;
import com.hsj.common.system.entity.SysUserRoleDo;
import com.hsj.common.system.service.IMenuPrivilegeService;
import com.hsj.common.system.service.ISysMenuService;
import com.hsj.common.system.service.ISysRoleMenuService;
import com.hsj.common.system.service.ISysUserRoleService;
import com.hsj.common.system.vo.request.ReqBatchDelSysMenuVo;
import com.hsj.common.system.vo.request.ReqSysMenuWithChildrenVo;
import com.hsj.common.system.vo.response.RespSysMenuWithChildrenVo;
import com.hsj.common.system.vo.response.RespUserPermissionVo;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;


/**
 *  系统菜单 Service 接口实现类
 *  @Author: Czy
 *  @Date: 2024-01-23 23:03:26
 *  @Email: 314170122@qq.com
 */
@Service
public class SysMenuServiceImpl extends BaseServiceImpl<SysMenuDo> implements ISysMenuService {

    private ISysUserRoleService iSysUserRoleService;

    private IMenuPrivilegeService iMenuPrivilegeService;

    private ISysRoleMenuService iSysRoleMenuService;

    private ISysMenuDao iSysMenuDao;

    public SysMenuServiceImpl(ISysUserRoleService iSysUserRoleService, ISysRoleMenuService iSysRoleMenuService, IMenuPrivilegeService iMenuPrivilegeService, ISysMenuDao iSysMenuDao){
        this.iSysRoleMenuService = iSysRoleMenuService;
        this.iSysUserRoleService = iSysUserRoleService;
        this.iMenuPrivilegeService = iMenuPrivilegeService;
        this.iSysMenuDao = iSysMenuDao;
    }

    @Autowired
    public void setBaseDao(ISysMenuDao baseDao) {
        super.setBaseDao(baseDao);
    }

    @Override
    public RespUserPermissionVo loadMenuByUserId(String userId) {
        RespUserPermissionVo resp = new RespUserPermissionVo();
        resp.setMenu(new ArrayList<>());
        resp.setDashboardGrid(new ArrayList<String>(){
            private static final long serialVersionUID = 8687167600818373124L;
            {
                add("welcome");
                add("ver");
                add("time");
                add("progress");
                add("echarts");
                add("about");
            }
        });
        /**
         * 加载所有用户权限关系数据
         */
        List<SysUserRoleDo> sysUserRoleDos = iSysUserRoleService.loadListByColumn(SysUserRoleDo::getUserId, userId);
        if(CollectionUtils.isEmpty(sysUserRoleDos)) return resp;
        /**
         * 根据角色id获取关联的所有菜单id
         */
        SmCriteria criteria = new SmCriteria.LambdaSmCriteriaBuild<SysRoleMenuDo>().in(SysRoleMenuDo::getRoleId, sysUserRoleDos.stream().map(SysUserRoleDo::getRoleId).collect(Collectors.toList())).build();
        List<SysRoleMenuDo> sysRoleMenuList = iSysRoleMenuService.getList(criteria);
        if(CollectionUtils.isEmpty(sysRoleMenuList)) return resp;

        /**
         * 根据菜单id获取所有菜单
         */
        criteria = new SmCriteria.LambdaSmCriteriaBuild<SysMenuDo>().in(SysMenuDo::getId, sysRoleMenuList.stream().map(SysRoleMenuDo::getMenuId).collect(Collectors.toList())).build();
        List<SysMenuDo> list = super.getList(criteria, Pager.Order.asc, "sortIndex");

        resp.setMenu(processToTreeMenu(list));

        criteria = new SmCriteria.LambdaSmCriteriaBuild<MenuPrivilegeDo>().in(MenuPrivilegeDo::getMenuId, sysRoleMenuList.stream().map(SysRoleMenuDo::getMenuId).collect(Collectors.toList())).build();
        List<MenuPrivilegeDo> menuPrivilegeDos = iMenuPrivilegeService.getList(criteria);
        resp.setPermission(menuPrivilegeDos.stream().map(MenuPrivilegeDo::getCode).collect(Collectors.toList()));
        return resp;
    }

    public List<RespSysMenuWithChildrenVo> convert(List<SysMenuDo> list){
        return list.stream().map(i -> {
            RespSysMenuWithChildrenVo resp = new RespSysMenuWithChildrenVo();
            RespSysMenuWithChildrenVo.MenuMeta menuMeta = new RespSysMenuWithChildrenVo.MenuMeta();
            resp.setParentId(i.getParentId());
            resp.setId(i.getId());
            resp.setComponent(i.getView());
            resp.setName(i.getName());
            resp.setPath(i.getRoutePath());
            resp.setChildren(new ArrayList<>());
            resp.setRedirect(i.getRedirectUrl());
            resp.setSortIndex(i.getSortIndex());
            if(!StringUtils.isEmpty(i.getAlias())) menuMeta.setTitle(i.getAlias());
            if(!StringUtils.isEmpty(i.getActive())) menuMeta.setActive(i.getActive());
            if(!StringUtils.isEmpty(i.getTag())) menuMeta.setTag(i.getTag());
            if(!StringUtils.isEmpty(i.getIcon())) menuMeta.setIcon(i.getIcon());
            if(!StringUtils.isEmpty(i.getType())) menuMeta.setType(i.getType());
            if(i.getHidden() != null) menuMeta.setHidden(i.getHidden());
            if(!StringUtils.isEmpty(i.getColor())) menuMeta.setColor(i.getColor());
            if(i.getHiddenBreadcrumb() != null) menuMeta.setHiddenBreadcrumb(i.getHiddenBreadcrumb());
            if(i.getFullPage() != null) menuMeta.setFullpage(i.getFullPage());
            resp.setMeta(menuMeta);
            return resp;
        }).collect(Collectors.toList());
    }

    private List<RespSysMenuWithChildrenVo> processToTreeMenu(List<SysMenuDo> list){
        /**
         * 过滤出所有一级菜单
         */
        List<SysMenuDo> firstMenu = list.stream().filter(i -> i.getLevel() == 1).collect(Collectors.toList());

        /**
         * 过滤出所有二级菜单
         */
        List<SysMenuDo> secondMenu = list.stream().filter(i -> i.getLevel() == 2).collect(Collectors.toList());

        /**
         * 过滤出所有三级菜单
         */
        List<SysMenuDo> thirdMenu = list.stream().filter(i -> i.getLevel() == 3).collect(Collectors.toList());

        /**
         * 过滤出所有四级菜单
         */
        List<SysMenuDo> forthMenu = list.stream().filter(i -> i.getLevel() == 3).collect(Collectors.toList());


        List<RespSysMenuWithChildrenVo> respForthMenu = convert(forthMenu);
        List<RespSysMenuWithChildrenVo> respThirdMenu = convert(thirdMenu);
        List<RespSysMenuWithChildrenVo> respSecondMenu = convert(secondMenu);
        List<RespSysMenuWithChildrenVo> respFirstMenu = convert(firstMenu);
        respThirdMenu.forEach(i -> i.getChildren().addAll(respForthMenu.stream().filter(ii -> Objects.equals(ii.getParentId(), i.getId())).collect(Collectors.toList())));
        respSecondMenu.forEach(i -> i.getChildren().addAll(respThirdMenu.stream().filter(ii -> Objects.equals(ii.getParentId(), i.getId())).collect(Collectors.toList())));
        respFirstMenu.forEach(i -> i.getChildren().addAll(respSecondMenu.stream().filter(ii -> Objects.equals(ii.getParentId(), i.getId())).collect(Collectors.toList())));
        return respFirstMenu;
    }

    @Override
    public List<RespSysMenuWithChildrenVo> loadAllMenu() {
        List<SysMenuDo> list = super.allList();
        Comparator<SysMenuDo> sort = Comparator.comparing(SysMenuDo::getSortIndex);
        return processToTreeMenu(list.stream().sorted(sort).collect(Collectors.toList()));
    }

    @Override
    public Integer editSysMenu(ReqSysMenuWithChildrenVo i) {
        SysMenuDo sysMenuDo = new SysMenuDo();
        sysMenuDo.setParentId(i.getParentId());
        sysMenuDo.setView(i.getComponent());
        sysMenuDo.setName(i.getName());
        sysMenuDo.setSortIndex(i.getSortIndex() == null ? 0 : i.getSortIndex());
        sysMenuDo.setRoutePath(i.getPath());
        sysMenuDo.setRedirectUrl(i.getRedirect());
        sysMenuDo.setSortIndex(i.getSortIndex());
        if(!StringUtils.isEmpty(i.getMeta().getTitle())) sysMenuDo.setAlias(i.getMeta().getTitle());
        if(!StringUtils.isEmpty(i.getMeta().getTag())) sysMenuDo.setTag(i.getMeta().getTag());
        if(!StringUtils.isEmpty(i.getMeta().getIcon())) sysMenuDo.setIcon(i.getMeta().getIcon());
        if(!StringUtils.isEmpty(i.getMeta().getType())) sysMenuDo.setType(i.getMeta().getType());
        if(i.getMeta().getHidden() != null) sysMenuDo.setHidden(i.getMeta().getHidden());
        if(!StringUtils.isEmpty(i.getMeta().getColor())) sysMenuDo.setColor(i.getMeta().getColor());
        if(i.getMeta().getHiddenBreadcrumb() != null) sysMenuDo.setHiddenBreadcrumb(i.getMeta().getHiddenBreadcrumb());
        if(i.getMeta().getFullpage() != null) sysMenuDo.setFullPage(i.getMeta().getFullpage());
        if(!StringUtils.isEmpty(i.getMeta().getActive())) sysMenuDo.setActive(i.getMeta().getActive());

        /**
         * 新增
         */
        if(i.getId() == null) {
            Serializable id = this.insert(sysMenuDo);
            /**
             * 上级菜单
             */
            if(i.getParentId() != null){
                SysMenuDo parentMenu = super.get(i.getParentId());
                sysMenuDo.setLevel(parentMenu.getLevel() + 1);
                sysMenuDo.setPath(parentMenu.getPath() + "," + id);
            }else{
                sysMenuDo.setLevel(0);
                sysMenuDo.setPath(id.toString());
            }
            sysMenuDo.setId(Integer.valueOf(id.toString()));
            this.update(sysMenuDo);
            if(!CollectionUtils.isEmpty(i.getApiList())){
                iMenuPrivilegeService.batchInsert(i.getApiList().stream().map(e ->
                        MenuPrivilegeDo.builder().menuId(Integer.valueOf(id.toString()))
                                .url(e.getUrl()).code(e.getCode()).build()).collect(Collectors.toList()));
            }
            return Integer.valueOf(id.toString());
        }else{
            sysMenuDo.setId(i.getId());
            this.update(sysMenuDo);
            return i.getId();
        }
    }

    @Override
    public Integer batchDelSysMenu(ReqBatchDelSysMenuVo vo) {
        Integer ret = 0;
        if(!CollectionUtils.isEmpty(vo.getIds())){
            for(String str : vo.getIds()){
                ret += iSysMenuDao.deleteMenu(str);
            }
        }
        return ret;
    }
}
